package com.yangzc.lion.sys.security.sso;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.stereotype.Component;

import com.yangzc.lion.sys.security.service.IUserDetailsService;
import com.yangzc.lion.sys.util.StringUtil;

/**
 * 自动登录帮助类，用于与其他系统做单点登录时，获取到已通过验证的关键字（通常是用户名）
 */
@Component("autoLoginHelper")
public class AutoLoginHelper {
	protected static final Logger LOGGER = Logger
			.getLogger(AutoLoginHelper.class);

	@Resource(name = "userDetailsService")
	private IUserDetailsService userDetailsService;

	/**
	 * 根据关键字（通常是用户名）自动登录EKP，常用于与其他系统进行单点登录操作。
	 * 
	 * @param keyword
	 *            关键字（通常是用户名）
	 */
	public String doAutoLogin(String keyword, HttpServletRequest request) {
		return doAutoLogin(keyword, null, request);
	}

	/**
	 * 根据关键字（通常是用户名）自动登录EKP，常用于与其他系统进行单点登录操作。
	 * 
	 * @param keyword
	 *            关键字
	 * @param type
	 *            关键字类型，可选值为keyword|id|username
	 * @return 用户名
	 */
	public String doAutoLogin(String keyword, String type,
			HttpServletRequest request) {

		if (!hasLogin() || getCurrentUserLoginName().equals(keyword)) {

			if (StringUtil.isNull(keyword))
				return null;
			UserDetails userDetails = null;
			try {
				if ("email".equals(type)) {
					userDetails = this.userDetailsService
							.loadUserByUserEmail(keyword);
				} else if ("id".equals(type)) {
					userDetails = this.userDetailsService
							.loadUserByUserId(keyword);
				} else {
					userDetails = this.userDetailsService
							.loadUserByUsername(keyword);
				}
			} catch (UsernameNotFoundException notFound) {
				LOGGER.warn("自动登录失败！[keyword=" + keyword + "]");
				return null;
			}
			PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(
					userDetails, userDetails.getPassword(),
					userDetails.getAuthorities());
			authentication.setDetails(new WebAuthenticationDetails(request));
			SecurityContextHolder.getContext()
					.setAuthentication(authentication);
			request.getSession(true).setAttribute("SPRING_SECURITY_CONTEXT",
					SecurityContextHolder.getContext());
		}
		return getCurrentUserLoginName();
	}

	/**
	 * 是否已经登录
	 * 
	 * @return
	 */
	public boolean hasLogin() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		return authentication != null;
	}

	/**
	 * 获取当前登录用户的登录名
	 * 
	 * @return
	 */
	public String getCurrentUserLoginName() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		if (authentication != null) {
			return authentication.getName();
		} else {
			return null;
		}
	}

	/**
	 * 执行注销操作
	 * 
	 * @param request
	 * @param response
	 */
	public void doLogout(HttpServletRequest request,
			HttpServletResponse response) {
		Cookie terminate = new Cookie(
				TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
				null);
		terminate.setMaxAge(0);
		response.addCookie(terminate);
		HttpSession session = request.getSession();
		session.invalidate();
		SecurityContextHolder.getContext().setAuthentication(null);
	}

	@Resource(name = "userDetailsService")
	public void setUserDetailsService(IUserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

}
